<template>
  <div class="form">
    <van-form ref="aform">
      <van-cell-group inset :title="formItem?.title" v-for="(formItem, formItemIndex) in config.formItems"
                      :key="formItemIndex">
        <template v-for="(item,index) in formItem.cells" :key="index">
          <!-- 输入框 -->
          <van-field v-if="item.type === 'input' && item.show !== false" v-model="cpConfig.formData[item.name]"
                     :label="item.label"
                     :label-align="item.labelAlign || cpConfig.labelAlign"
                     :label-width="item.labelWidth || cpConfig.labelWidth"
                     :name="item.name" :placeholder="item.placeholder"
                     :required="item.required" :rules="cpConfig?.rules?.[item.name as any]"
                     v-bind="typeof item.bind == 'function' ? item.bind(item) : { clearable: true, ...item.bind }"/>

          <!-- 选择器 | 地址选择器 -->
          <van-field v-if="['select','region'].includes(item.type) && item.show !== false"
                     v-model="cpConfig.formData[item.name + 'Label']"
                     :label="item.label" readonly is-link
                     :label-align="item.labelAlign || cpConfig.labelAlign"
                     :label-width="item.labelWidth || cpConfig.labelWidth"
                     :name="item.name" :placeholder="item.placeholder"
                     :required="item.required" :rules="cpConfig?.rules?.[item.name as any]"
                     v-bind="typeof item.bind == 'function' ? item.bind(item) : { clearable: true, ...item.bind }"
                     @click="showPicker(item)"/>

          <!-- 日期选择器 | 时间选择器 | 日历选择器 -->
          <van-field v-if="['datePicker','timePicker','calendar'].includes(item.type) && item.show !== false"
                     v-model="cpConfig.formData[item.name]"
                     :label="item.label" readonly is-link
                     :label-align="item.labelAlign || cpConfig.labelAlign"
                     :label-width="item.labelWidth || cpConfig.labelWidth"
                     :name="item.name" :placeholder="item.placeholder"
                     :required="item.required" :rules="cpConfig?.rules?.[item.name as any]"
                     v-bind="typeof item.bind == 'function' ? item.bind(item) : { clearable: true, ...item.bind }"
                     @click="showPicker(item)"/>

          <!-- radio单选框 | checkbox复选框 | 开关 | 插槽-->
          <van-field v-if="['radio','checkbox','switch','slot'].includes(item.type) && item.show !== false"
                     :label="item.label"
                     :label-align="item.labelAlign || cpConfig.labelAlign"
                     :label-width="item.labelWidth || cpConfig.labelWidth"
                     :name="item.name" :placeholder="item.placeholder"
                     :required="item.required" :rules="cpConfig?.rules?.[item.name as any]"
                     v-bind="typeof item.bind == 'function' ? item.bind(item) : { clearable: true, ...item.bind }">
            <template #input>
              <van-radio-group v-model="cpConfig.formData[item.name]" direction="horizontal"
                               v-bind="typeof item.bind == 'function' ? item.bind(item) : { ...item.bind }"
                               @change="handleFn($event, item)" v-if="item.type ==='radio'">
                <van-radio v-for="(radioItem, index) in cpConfig.enums[item.enumKey as any]" :key="index"
                           :name="radioItem.value"
                           v-bind="typeof item.bind == 'function' ? item.bind(item) : { ...item.bind }">
                  {{ radioItem.label }}
                </van-radio>
              </van-radio-group>

              <van-checkbox-group v-model="cpConfig.formData[item.name]" direction="horizontal"
                                  v-bind="typeof item.bind == 'function' ? item.bind(item) : { ...item.bind }"
                                  @change="handleFn($event, item)" v-else-if="item.type ==='checkbox'">
                <van-checkbox v-for="(checkboxItem, index) in cpConfig.enums[item.enumKey as any]" :key="index"
                              :name="checkboxItem.value"
                              v-bind="typeof item.bind == 'function' ? item.bind(item) : { ...item.bind }">
                  {{ checkboxItem.label }}
                </van-checkbox>
              </van-checkbox-group>

              <van-switch v-model="cpConfig.formData[item.name]" :name="item.name" @change="handleFn($event, item)"
                          v-else-if="item.type ==='switch'"/>

              <slot :name="item.name" v-else></slot>
            </template>
          </van-field>
        </template>
      </van-cell-group>
    </van-form>

    <div class="footer">
      <template v-for="(item, index) in cpConfig.operatorList" :key="index">
        <van-button class="mt-16" v-bind="item.bind" @click="onSubmit(item)">
          {{ item.label }}
        </van-button>
      </template>
    </div>
  </div>


  <!--  这边弹窗不总写的原因，是因为如果总写外部的poup层，里面的内容根据v-if来显隐，关闭时候，动画会不自然-->
  <!-- 选择器弹出层 -->
  <van-popup :show="showPickerPopup" position="bottom" teleport="body" destroy-on-close>
    <van-picker :columns="cpConfig.enums[currentPicker.enumKey]" :columns-field-names="currentPicker.columnsFieldNames"
                :title="currentPicker.label"
                v-bind="typeof currentPicker.bind == 'function' ? currentPicker.bind(currentPicker) : { ...currentPicker.bind }"
                @cancel="showPickerPopup = false" @confirm="handleFn"/>
  </van-popup>

  <!--  地址选择器-->
  <van-popup :show="showRegionPopup" position="bottom" teleport="body" destroy-on-close>
    <van-cascader
        :title="currentPicker.label" :options="regionData"
        v-bind="typeof currentPicker.bind == 'function' ? currentPicker.bind(currentPicker) : { ...currentPicker.bind }"
        @close="showRegionPopup = false" @finish="handleFn"/>
  </van-popup>

  <!-- 日期选择器弹出层 -->
  <van-popup :show="showDatePopup" position="bottom" teleport="body" destroy-on-close>
    <van-date-picker
        :title="currentPicker.label"
        v-bind="typeof currentPicker.bind == 'function' ? currentPicker.bind(currentPicker) : { ...currentPicker.bind }"
        @cancel="showDatePopup = false" @confirm="handleFn"/>
  </van-popup>

  <!--  时间选择器弹出层-->
  <z-time v-model="showTimePopup" teleport="body" round
          :value="cpConfig.formData[currentPicker.name]" :title="currentPicker.label"
          @click-overlay="showTimePopup = false" @update:value="handleFn"/>

  <!--  日历选择器弹出层-->
  <van-calendar :show="showCalendarPopup" position="bottom" :title="currentPicker.label" teleport="body"
                v-bind="typeof currentPicker.bind == 'function' ? currentPicker.bind(currentPicker) : { ...currentPicker.bind }"
                @close="showCalendarPopup = false" @confirm="handleFn"/>
</template>

<script lang="ts" setup>
import {computed, ref} from 'vue'
import {useCascaderAreaData} from '@vant/area-data';
import {getValueLabel} from '@/utils/region'
import type {CompType, Cells, FormItem, Config, Settings} from '@/components/Z-UI/ZForm/type'
import ZTime from "@/components/Z-UI/ZTime/index.vue"; //时间选择器

// Props 定义
const props = withDefaults(defineProps<{
  config: Config
  settings?: Settings
}>(), {
  settings: () => ({
    dateSeparator: '-',
    timeSeparator: ':',
    regionSeparator: '/'
  })
})

const emit = defineEmits(['handleEvent'])

// 响应式数据
const aform: any = ref(null)
const showPickerPopup = ref(false)
const showDatePopup = ref(false)
const showTimePopup = ref(false)
const showCalendarPopup = ref(false)
const showRegionPopup = ref(false)
const currentPicker = ref<any>({})
const regionData = useCascaderAreaData();

const cpConfig = computed(() => {
  const config = props.config
  config.formItems.forEach((d: FormItem) => {
    d.cells.forEach(cell => {
      // 处理时间限制
      if (cell.bind?.minDate) {
        if (typeof cell.bind?.minDate === 'function') {
          return cell.bind.minDate()
        }
        return cell.bind?.minDate
      }
      if (cell.bind?.maxDate) {
        if (typeof cell.bind?.maxDate === 'function') {
          return cell.bind.maxDate()
        }
        return cell.bind?.maxDate
      }

      // 特殊处理select类型的数据，因为select类型的数据，label和value是要两个值绑定的，默认值要赋值给lablel
      if (cell.type === 'select' && cell.enumKey && config.enums[cell.enumKey]) {
        let res = config.enums[cell.enumKey].find(item => item[cell?.columnsFieldNames?.value] === config.formData[cell.name])
        if (res) config.formData[`${cell.name}Label`] = res[cell?.columnsFieldNames?.text]
      }
      // 特殊处理region类型的数据，因为region类型的数据，label和value是要两个值绑定的，默认值要赋值给lablel
      if (cell.type === 'region' && config.formData[cell.name]) {
        let res = getValueLabel(config.formData[cell.name].split(props.settings.regionSeparator), regionData)
        if (res) config.formData[`${cell.name}Label`] = res.join(props.settings.regionSeparator)
      }
    })
  })

  // 处理按钮
  if (config.operatorList.length) {
    config.operatorList.forEach((d) => {
      if (d.event) formaterFun(d)
    })
  }
  return config
})

const formaterFun = (d: any) => {
  if (d.event === 'validate') return d.event = validate
  if (d.event === 'reset') return d.event = reset
}

// 显示选择器
const showPicker = (item: Cells) => {
  currentPicker.value = item as Cells
  let type = item.type
  if (type === 'select') {
    showPickerPopup.value = true
  } else if (type === 'datePicker') {
    showDatePopup.value = true
  } else if (type === 'timePicker') {
    showTimePopup.value = true
  } else if (type === 'calendar') {
    showCalendarPopup.value = true
  } else if (type === 'region') {
    showRegionPopup.value = true
  }
}

// 关闭选择器
const closePicker = () => {
  let type = currentPicker.value.type
  if (type === 'select') {
    showPickerPopup.value = false
  } else if (type === 'region') {
    showRegionPopup.value = false
  } else if (type === 'datePicker') {
    showDatePopup.value = false
  } else if (type === 'timePicker') {
    showTimePopup.value = false
  } else if (type === 'calendar') {
    showCalendarPopup.value = false
  }
  currentPicker.value = {}
}

const handleFn = (e: any, item?: Cells) => {
  console.log('e==', e)
  let type = currentPicker.value.type
  if (type === 'select') {  // 选择-确认
    props.config.formData[currentPicker.value.name] = e.selectedOptions[0][currentPicker.value.columnsFieldNames?.value]
  } else if (type === 'datePicker') { // 日期-确认
    props.config.formData[currentPicker.value.name] = e.selectedValues?.join(props.settings.dateSeparator);
  } else if (type === 'timePicker') { // 时间-确认
    // vant的时间选择器赋值方式
    // props.config.formData[currentPicker.value.name] = e.selectedValues?.join(props.settings.timeSeparator);
    // ZTime时间选择器赋值方式
    props.config.formData[currentPicker.value.name] = e;
  } else if (type === 'calendar') { // 日历-确认
    props.config.formData[currentPicker.value.name] = formatDate(e)
  } else if (type === 'region') { // 地址-确认
    props.config.formData[currentPicker.value.name] = e.selectedOptions.map((item: any) => item.value).join(props.settings.regionSeparator)
  } else if (type === 'radio') { // radio-切换
    if (item?.event) return emit('handleEvent', item?.event, cpConfig.value.formData[item.name])
  } else if (type === 'checkbox') { // checkbox-切换
    if (item?.event) return emit('handleEvent', item?.event, cpConfig.value.formData[item.name])
  } else if (type === 'checkbox') { // 开关-切换
    if (item?.event) return emit('handleEvent', item?.event, cpConfig.value.formData[item.name])
  }

  if (currentPicker.value?.event) {
    emit('handleEvent', currentPicker.value?.event, props.config.formData[currentPicker.value.name])
  }
  closePicker()
}

const formatDate = (date: Date) => {
  return `${date.getFullYear()}/${date.getMonth() + 1}/${date.getDate()}`;
};

const onSubmit = (val: any) => {
  if (val.disabled) return;
  val.disabled = true;
  val.event(val)
  setTimeout(() => {
    val.disabled = false;
  }, 1000); // 默认1000毫秒，可以通过指令参数指定
}

/**
 * 提交
 */
const validate = () => {
  return new Promise((resolve: any, reject: any) => {
    aform.value.validate().then(() => {
      const result = {
        valid: true,
        formData: cpConfig.value.formData,
      }
      // 触发提交事件
      emit('handleEvent', 'validate', {
        valid: true,
        formData: cpConfig.value.formData,
      })
      resolve(result)
    }).catch(() => {
      const result = {
        valid: false,
      }
      // 触发提交事件
      emit('handleEvent', 'validate', result)
      reject(result)
    })
  })
}

/**
 * 重置表单+清空校验
 */
const reset = () => {
  Object.keys(cpConfig.value.formData).forEach(d => {
    // 数组的需要特殊处理
    if (Array.isArray(cpConfig.value.formData[d])) {
      cpConfig.value.formData[d] = []
    } else {
      cpConfig.value.formData[d] = ''
    }
  })
  emit('handleEvent', 'reset', null)
  setTimeout(() => {
    clearValidate()
  }, 100)
}

/**
 * 清空校验
 */
const clearValidate = () => {
  return aform.value.resetValidation()
}

// 子组件名称
defineExpose({
  clearValidate,
  reset,
  validate
})

</script>

<style scoped lang="scss">
.form {
  width: 100%;
  padding-bottom: 100px;
}

.footer {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  background-color: #fff;
  padding: 10px 15px;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: space-around;
}

:deep(.van-button) {
  margin: 0 5px;
}
</style>